package cn.wen233.srpc.basic.utils;

/**
 * id生成器工具
 *
 * @author wenei
 * @date 2021-10-18 15:17
 */
public class IdUtils {

    /**
     * 雪花id生成器
     */
    private static class SnowflakeIdGenerator {

        /**
         * 2000-1-1 00:00:00 时间戳
         */
        private final static long START_TIMESTAMP = 946656000000L;

        /**
         * 序列号长度
         */
        private final static long SEQUENCE_BIT = 12;

        /**
         * 机器长度
         */
        private final static long MACHINE_BIT = 8;

        /**
         * 数据中心长度标识
         */
        private final static long DATACENTER_BIT = 2;

        private final static long MACHINE_OFFSET = SEQUENCE_BIT;

        private final static long DATACENTER_OFFSET = MACHINE_OFFSET + MACHINE_BIT;

        private final static long TIMESTAMP_OFFSET = DATACENTER_OFFSET + DATACENTER_BIT;

        private final static long SEQUENCE_MAX = (1 << SEQUENCE_BIT) - 1;

        private long datacenterId;

        private long machineId;

        private long sequence = 0;

        private long lastTimeStamp = -1;

        private SnowflakeIdGenerator(long datacenterId, long machineId) {
            this.datacenterId = datacenterId;
            this.machineId = machineId;
        }

        public synchronized long nextId() {
            long currentTimeStamp = System.currentTimeMillis();
            if (currentTimeStamp == lastTimeStamp) {
                sequence = (sequence + 1) & SEQUENCE_MAX;
                if (sequence == 0) {
                    while (true) {
                        if (System.currentTimeMillis() > currentTimeStamp) {
                            break;
                        }
                    }
                }
            } else {
                sequence = 0;
            }
            lastTimeStamp = currentTimeStamp;
            return (currentTimeStamp - START_TIMESTAMP) << TIMESTAMP_OFFSET
                    | datacenterId << DATACENTER_OFFSET
                    | machineId << MACHINE_OFFSET
                    | sequence;
        }

        private static volatile SnowflakeIdGenerator INSTANCE = null;

        /**
         * 单例模式 双重检验锁
         * @return 雪花ID生成单例
         */
        public static SnowflakeIdGenerator getInstance() {
            if (INSTANCE == null) {
                synchronized (SnowflakeIdGenerator.class) {
                    if (INSTANCE == null) {
                        INSTANCE = new SnowflakeIdGenerator(0, 0);
                    }
                }
            }
            return INSTANCE;
        }
    }

    public static long snowId() {
        return SnowflakeIdGenerator.getInstance().nextId();
    }

//    public static void main(String[] args) {
//        new Thread(() -> {
//            System.out.println(snowId());
//            System.out.println(snowId());
//            System.out.println(snowId());
//            System.out.println(snowId());
//        }).start();
//        System.out.println(snowId());
//        System.out.println(snowId());
//        System.out.println(snowId());
//        System.out.println(snowId());
//    }

}
